package com.smart.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 日期处理
 */
public class DateUtils {
    private final static Logger logger = LoggerFactory.getLogger(DateUtils.class);
    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    /**
     * 时间格式(yyyy-MM-dd HH:mm)
     */
    public final static String DATE_MINUTE_PATTERN = "yyyy-MM-dd HH:mm";
    /**
     * 时间格式(yyyy-MM-dd HH:mm)
     */
    public final static String DATE_TIME_M_PATTERN = "yyyy-MM-dd HH:mm";
    /**
     * 时间格式(HH:mm:ss)
     */
    public final static String TIME_PATTERN = "HH:mm:ss";
	/**
	 * 时间格式(yyyyMMdd)
	 */
	public final static String DATE_PATTERN_SIMPLE = "yyyyMMdd";
	/**
	 * 时间格式(yyyy)
	 */
	public final static String YEAR_PATTERN = "yyyy";
	/**
	 * 时间格式(MM)
	 */
	public final static String MONTH_PATTERN = "MM";
	/**
	 * 时间格式(dd)
	 */
	public final static String DAY_PATTERN = "dd";
	/**
	 * 时间格式(yyyy-MM)
	 */
	public final static String YEAR_MONTH_PATTERN = "yyyy-MM";
	/**
	 * 获取中文年月日
	 * @param date
	 * @return
	 */
	public static String parseZNDate(Date date) {
		return DateUtils.format(date, YEAR_PATTERN) +"年"+
				DateUtils.format(date, MONTH_PATTERN) +"月"+
				DateUtils.format(date,DAY_PATTERN) + "日";
	}
    /**
     * @Deprecated
     * 格式日期使用 formatDate
     * @param date
     * @return
     * @version: 2019年1月11日 下午1:26:11
     * @author: zhouwc
     */
    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }
    public static String formatDate(Date date) {
    	return format(date, DATE_PATTERN);
    }
    public static String formatDateTime(Date date) {
    	return format(date, DATE_TIME_PATTERN);
    }

    public static String format(Date date, String pattern) {
		try {
			if (date != null) {
				SimpleDateFormat df = new SimpleDateFormat(pattern);
				return df.format(date);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
    }
    public static Date parseDate(String dateStr) {
    	Date parseDate = null;
    	if(!StringUtils.isBlank(dateStr)) {
    		SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN);
    		try {
    			parseDate = df.parse(dateStr);
    		} catch (ParseException e) {
    			e.printStackTrace();
    		}
    	}
    	return parseDate;
    }
    public static Date parseDate(String dateStr,String pattern) {
    	Date parseDate = null;
    	if(!StringUtils.isBlank(dateStr)) {
    		SimpleDateFormat df = new SimpleDateFormat(pattern);
    		try {
    			parseDate = df.parse(dateStr);
			} catch (ParseException e) {
				e.printStackTrace();
			}
    	}
    	return parseDate;
    }
    public static Date parseAllDate(String src) {
    	Date parseDate = null;

		try {
			if (StringUtils.isBlank(src))
				return null;
			if (src.length() == 10) {
				SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
				parseDate = dateFormat1.parse(src);
			} else if (src.length() == 19) {
				SimpleDateFormat dateTimeFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				parseDate = dateTimeFormat1.parse(src);
			} else if (src.length() > 19) {
				src = src.substring(0, 19);
				SimpleDateFormat dateTimeFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				parseDate = dateTimeFormat1.parse(src);
			} else {
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new RuntimeException("日期时间解析失败,请检查日期格式是否满足yyyy-mm-dd或yyyy-mm-dd hh:mi:ss");

		}
		return parseDate;
		
	}

	public static String subDays(String date,Integer days){
		Date now = parseDate(date, DATE_TIME_PATTERN);
		//获取三十天前日期
		Calendar theCa = Calendar.getInstance();
		theCa.setTime(now);
		theCa.add(theCa.DATE, -30);//最后一个数字30可改，30天的意思
		Date start = theCa.getTime();
		String startDate = format(start,DATE_TIME_PATTERN);//三十天之前日期
		return startDate;
	}


    /**
     * 计算距离现在多久，非精确
     *
     * @param date
     * @return
     */
    public static String getTimeBefore(Date date) {
        Date now = new Date();
        long l = now.getTime() - date.getTime();
        long day = l / (24 * 60 * 60 * 1000);
        long hour = (l / (60 * 60 * 1000) - day * 24);
        long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        String r = "";
        if (day > 0) {
            r += day + "天";
        } else if (hour > 0) {
            r += hour + "小时";
        } else if (min > 0) {
            r += min + "分";
        } else if (s > 0) {
            r += s + "秒";
        }
        r += "前";
        return r;
    }

    /**
     * 计算距离现在多久，精确
     *
     * @param date
     * @return
     */
    public static String getTimeBeforeAccurate(Date date) {
        Date now = new Date();
        long l = now.getTime() - date.getTime();
        long day = l / (24 * 60 * 60 * 1000);
        long hour = (l / (60 * 60 * 1000) - day * 24);
        long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        String r = "";
        if (day > 0) {
            r += day + "天";
        }
        if (hour > 0) {
            r += hour + "小时";
        }
        if (min > 0) {
            r += min + "分";
        }
        if (s > 0) {
            r += s + "秒";
        }
        r += "前";
        return r;
    }
    /**
     * 特定日期时间是否在日期时间范围内
     * 
     * @param nowValid 特定日期
     * @param validStart 开始日期时间
     * @param validEnd 结束日期时间
     * @return nowValid>=validStart && validStart<=validEnd return true 
     * @version: 2019年1月9日 上午9:11:57
     * @author: zhouwc
     */
	public static boolean isInDateRange(Date nowValid, Date validStart, Date validEnd) {
		if(validStart == null || validEnd ==null) {
			return false;
		}
		if(nowValid.before(validStart)) {
			return false;
		}
		if(nowValid.after(validEnd)) {
			return false;
		}
		return true;
	}
	/**
	 * 特定日期时间是否在日期时间范围内
	 * 
	 * @param nowValid 特定日期
	 * @param validStart 开始日期时间
	 * @param validEnd 结束日期时间
	 * @return nowValid大于等于validStart 并且 nowValid小于validEnd return true 
	 * @version: 2019年6月28日 上午9:11:57
	 * @author: zhouwc	 
	 * */
	public static boolean isInDateRangeLeft(Date nowValid, String validStart, String validEnd) {
		if(nowValid == null || validStart == null || validEnd ==null) {
			return false;
		}
		
		if(nowValid.before(parseDate(validStart,DATE_TIME_PATTERN))) {
			//当前时间小于开始时间
			return false;
		}
//		if(nowValid.after(parseDate(validEnd,DATE_TIME_PATTERN))) {
//			//结束时间小于当前时间
//			return false;
//		}
		if(!parseDate(validEnd,DATE_TIME_PATTERN).after(nowValid)) {
			//结束时间小于当前时间
			return false;
		}
		return true;
	}
	/**
	 * 获取今日0点时间
	 * @return
	 * @version: 2019年1月10日 下午3:50:36
	 * @author: zhouwc
	 */
	public static Date getTodayStartDate() {
//		Calendar calendar = Calendar.getInstance();
//        calendar.setTime(new Date());
//        calendar.set(Calendar.HOUR_OF_DAY, 0);
//        calendar.set(Calendar.MINUTE, 0);
//        calendar.set(Calendar.SECOND, 0);
//        Date zero = calendar.getTime();
        Date date = new Date();
		Date zero = parseDate(formatDateTime(date));
		return zero;
	}
	/**
	 * 获取今日0点时间字符串
	 */
	public static String getTodayStartDateTimeStr() {
		Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date zero = calendar.getTime();
		String s = formatDateTime(zero);
		return s;
	}

	public static Date getNowDateTime() {
		return new Date();
	}
	/**
	 * 获取今日0点0分0秒的日期
	 * 
	 * @return
	 * @version: 2019年1月14日 下午2:29:06
	 * @author: zhouwc
	 */
	public static Date getTodayZeroDate() {
		Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date zero = calendar.getTime();
		return zero;
	}
	/**
	 * 当前日期加上指定天数返回一个新日期
	 * 
	 * @param cpDateValue
	 * @return
	 * @version: 2019年1月14日 下午2:25:59
	 * @author: zhouwc
	 */
	public static Date addNowDate(Integer cpDateValue) {
		if(cpDateValue == null || cpDateValue == 0) {
			return DateUtils.getTodayZeroDate();
		}
		Calendar ca = Calendar.getInstance();
		ca.add(Calendar.DATE, cpDateValue);
		return ca.getTime();
	}
	public static Date addDate(Date date,int v) {
		Calendar ca = Calendar.getInstance();
		ca.setTime(date);
		ca.add(Calendar.DATE, v);
		return ca.getTime();
	}
	/**
	 * 当前日期减去指定天数返回一个新日期
	 * 
	 * @param cpDateValue
	 * @return
	 * @version: 2019年1月14日 下午2:25:59
	 * @author: zhouwc
	 */
	public static Date minusNowDate(Integer cpDateValue) {
		if(cpDateValue == null || cpDateValue == 0) {
			return DateUtils.getTodayZeroDate();
		}
		Calendar ca = Calendar.getInstance();
		ca.add(Calendar.DATE, cpDateValue * -1);
		return ca.getTime();
	}

	/**
	 * 获取前num天的list（包含当前日期）
	 * @param num
	 * @return
	 */
	public static List<String> getDates(int num){
		List<String> list = new ArrayList<>();
		if (num > 0){
			for (int i = 0; i < num; i++) {
				Calendar calendar = Calendar.getInstance();
				calendar.add(Calendar.DATE, -i); //得到前一天
				Date date = calendar.getTime();
				DateFormat df = new SimpleDateFormat(DATE_PATTERN);
				list.add(df.format(date));
			}
		}
		if (num == 0){
			list.add(DateUtils.format(new Date(), DateUtils.DATE_PATTERN));
		}
		return list;
	}

	/**
	 * 获取上个月的天数list
	 * @param currentNum
	 * @param lastNum
	 * @return
	 */
	public static List<String> getMonthDates(int currentNum ,int lastNum){
		List<String> list = new ArrayList<>();
		if (currentNum > 0 && lastNum >0){
			for (int i = currentNum; i < lastNum+currentNum; i++) {
				Calendar calendar = Calendar.getInstance();
				calendar.add(Calendar.DATE, -i); //得到前一天
				Date date = calendar.getTime();
				DateFormat df = new SimpleDateFormat(DATE_PATTERN);
				list.add(df.format(date));
			}
		}
		return list;
	}

	/**
	 * 将毫秒转换成日期格式
	 * @param milliseconds
	 * @param dateFormatPattern
	 * @return
	 */
	public static Date millisecondToDate(Long milliseconds, String dateFormatPattern){
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormatPattern);
		String time = simpleDateFormat.format(new Date(milliseconds));
		return DateUtils.parseDate(time,DATE_TIME_PATTERN);
	}
	public static String getNowDateStr() {

		return new SimpleDateFormat(DATE_PATTERN).format(new Date());

	}

	/**
	 * 查询昨天日期
	 */
	public static String getLastDateStr() {
		return getLastDateStr(getNowDateStr());
	}

	/**
	 * 查询指定日期的上一天日期
	 * @param dateStr
	 * @return
	 */
	public static String getLastDateStr(String dateStr) {

		Calendar c = Calendar.getInstance(); 
		Date date = null;
		try {
			date = new SimpleDateFormat(DATE_PATTERN).parse(dateStr);
			c.setTime(date); 
			int day=c.get(Calendar.DATE); 
			c.set(Calendar.DATE,day-1); 
			String dayBefore=new SimpleDateFormat(DATE_PATTERN).format(c.getTime()); 
			return dayBefore;
		} catch (ParseException e) {
			e.printStackTrace(); 
		}
		return null;
	}
	/**
	 * 当前时间是否小于指定的时间点
	 * @param compareTime
	 * @return
	 */
	public static boolean isBeforeTime(String compareTime) {
		String nowTime = format(new Date(), TIME_PATTERN);
		if(nowTime.compareTo(compareTime) <0) {
			return true;
		}
		return false;
	}

	/**
	 * 时间后移小时 减一秒
	 * @param time
	 * @param num
	 * @return
	 * @throws ParseException
	 */
	public static String timeAddHoursMinusOneSeconds(String time,int num){
		SimpleDateFormat sd = new SimpleDateFormat(DATE_TIME_PATTERN);
		// 把当前得到的时间用date.getTime()的方法写成时间戳的形式，再加上8小时对应的毫秒数
		long rightTime = (long) (DateUtils.parseDate(time,DATE_TIME_PATTERN).getTime() + num * 60 * 60 * 1000) -1;
		// 把得到的新的时间戳再次格式化成时间的格式
		String newTime = sd.format(rightTime);
		return newTime;
	}

	/**
	 * 时间后移小时
	 * @param time
	 * @param num
	 * @return
	 * @throws ParseException
	 */
	public static String timeAddHours(String time,int num){
		SimpleDateFormat sd = new SimpleDateFormat(DATE_TIME_PATTERN);
		// 把当前得到的时间用date.getTime()的方法写成时间戳的形式，再加上8小时对应的毫秒数
		long rightTime = (long) (DateUtils.parseDate(time,DATE_TIME_PATTERN).getTime() + num * 60 * 60 * 1000);
		// 把得到的新的时间戳再次格式化成时间的格式
		String newTime = sd.format(rightTime);
		return newTime;
	}



	public static Long dateToMillis(Date time){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(time);
		return calendar.getTimeInMillis();
	}

	public static String getNowDateTimeStr() {
		return new SimpleDateFormat(DATE_TIME_PATTERN).format(new Date());
	}
	public static String getNowDateMinuteStr() {
		return new SimpleDateFormat(DATE_MINUTE_PATTERN).format(new Date());
	}


	/**
	 * <li>功能描述：时间相减得到天数
	 * @param beginDateStr
	 * @param endDateStr
	 * @return
	 * long
	 * @author Administrator
	 */
	public static long getDaySub(String beginDateStr,String endDateStr)
	{
		long day=0;
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Date beginDate = new Date();
		Date endDate = new Date();
		try
		{
			beginDate = format.parse(beginDateStr);
			endDate= format.parse(endDateStr);
			day=(endDate.getTime()-beginDate.getTime())/(24*60*60*1000);
			//System.out.println("相隔的天数="+day);
		} catch (ParseException e)
		{
			// TODO 自动生成 catch 块
			e.printStackTrace();
		}
		return day;
	}

	/**
	 * 获取月份的天数
	 * @param date
	 * @return
	 */
	public static int getDaysOfMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 如果当前时间是0点-17点(包含),则返回昨天日期
	 * 如果当前时间是17点-24点,则返回今天日期
	 * @return
	 */
    public static String getStationDailyDateStr() {
    	int nowHour = getNowHour();
    	if(nowHour<17){
			return getLastDateStr();
		}else{
			return getNowDateStr();
		}
	}

	/**
	 * 查询当前几点了
	 */
	public static int getNowHour() {
		Calendar instance = Calendar.getInstance();
		return instance.get(Calendar.HOUR_OF_DAY);
	}

	/**
	 * 传入一个字符串日期 格式yyyy-MM-dd  得到 n 个月之前的那天的字符串 yyyy-MM-dd
	 * @param now
	 * @return
	 */
	public static String getDayOfMonths(String now,String formatDate,Integer months){
		Date dNow = parseDate(now, formatDate);

		Date dBefore = new Date();
		Calendar calendar = Calendar.getInstance(); //得到日历
		calendar.setTime(dNow);//把当前时间赋给日历
		calendar.add(Calendar.MONTH, - months);  //设置为前3月
		dBefore = calendar.getTime();   //得到前3月的时间

		String format = format(dBefore, formatDate);

		return format;
	}

	/**
	 * 查询指定月份最后一日17:00:00的时间
	 * @param month 2019-08
	 * @return
	 */
	public static String getMonthEndDateOfSum(String month){
		String dateStr = month + "-01";
		Date date = DateUtils.parseDate(dateStr, DateUtils.DATE_PATTERN);
		int daysOfMonth = getDaysOfMonth(date);
		return month + "-"+daysOfMonth+" 17:00:00";
	}
	/**
	 * 查询指定月份最后一日
	 * @param month 2019-08
	 * @return
	 */
	public static String getMonthEndDate(String month){
		String dateStr = month + "-01";
		Date date = DateUtils.parseDate(dateStr, DateUtils.DATE_PATTERN);
		int daysOfMonth = getDaysOfMonth(date);
		return month + "-"+daysOfMonth;
	}

	/**
	 * 查询当前月份的上一个月份
	 * @param month 2019-08
	 * @return 2019-07
	 */
	public static String getLastMonth(String month){
		String[] split = month.split("-");
		int year = Integer.parseInt(split[0]);
		int nowMonth = Integer.parseInt(split[1]);
		int lastMonth = 0;
		int lastYear = year;
		if(nowMonth == 1){
			lastMonth = 12;
			lastYear = year-1;
		}else{
			lastMonth = nowMonth - 1;
		}
		String lastMonthStr = "";
		if(lastMonth<10){
			lastMonthStr = "0"+lastMonth;
		}else{
			lastMonthStr = ""+lastMonth;
		}
		String r = lastYear+"-"+lastMonthStr;
		return r;
	}
	/**
	 * 如果是本月最后一日,则获取本月月份,否则获取上月月份
	 */
	public static String getStationBillMonthStr() {

		Calendar instance = Calendar.getInstance();

		int year = instance.get(Calendar.YEAR);
		int month = instance.get(Calendar.MONTH)+1;
		int day = instance.get(Calendar.DAY_OF_MONTH);

		String dateStr = year + "-" + month + "-01";
		Date date = DateUtils.parseDate(dateStr, DateUtils.DATE_PATTERN);
		int daysOfMonth = getDaysOfMonth(date);
		String monthStr = String.valueOf(month);

		if(day == daysOfMonth){
			//当前日期是该月份最后一日,取本月月份
			if(month<10){
				monthStr = "0"+month;
			}
			return year + "-" + monthStr;
		}else{
			//取上个月份
			int lastMonth = month - 1;
			if(lastMonth == 0){
				monthStr = "12";
				return (year-1) + "-" + monthStr;
			}else{
				if(lastMonth<10){
					monthStr = "0"+lastMonth;
				}
				return year + "-" + monthStr;
			}
		}
	}

	/**
	 * 时间后移秒，用于解决mysql插入数据库大于500毫秒进位问题
	 * @param time
	 * @return
	 * @throws ParseException
	 */
	public static Date timeAddSeconds(Date time){
		String dateStr = format(time,DATE_TIME_PATTERN);
		SimpleDateFormat sd = new SimpleDateFormat(DATE_TIME_PATTERN);
		// 把当前得到的时间用date.getTime()的方法写成时间戳的形式，再加上8小时对应的毫秒数
		long rightTime = (long) (DateUtils.parseDate(dateStr,DATE_TIME_PATTERN).getTime() + 1000);
		// 把得到的新的时间戳再次格式化成时间的格式
		String newTime = sd.format(rightTime);
		return parseDate(newTime,DATE_TIME_PATTERN);
	}

	public static void main(String[] args) {

//		System.out.println(timeAddHours("2019-08-20 11:00:00",-24*30));
//		String month = "2019-04";
//		System.out.println(getMonthEndDateOfSum(month));
//		System.out.println(getMonthEndDateOfSum(getLastMonth(month)));
		Date todayStartDate = getTodayStartDate();
		String pattern = "yyyy-MM-dd HH:mm:ss:SSS";
		String format = format(todayStartDate, pattern);
		System.out.println(format);

	}


	/**
	 * 获取一定时间段内  每一天的日期
	 * @param begintTime  开始日期  yyyy-MM-dd
	 * @param endTime    结束日期  yyyy-MM-dd
	 * @return  每天的日期
	 */
	public static List<String> findDaysStr(String begintTime, String endTime) {

		SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);
		Date dBegin = null;
		Date dEnd = null;
		try {
			dBegin = sdf.parse(begintTime);
			dEnd = sdf.parse(endTime);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		//存放每一天日期String对象的daysStrList
		List<String> daysStrList = new ArrayList<String>();
		//放入开始的那一天日期String
		daysStrList.add(sdf.format(dBegin));

		Calendar calBegin = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		calBegin.setTime(dBegin);

		Calendar calEnd = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		calEnd.setTime(dEnd);

		// 判断循环此日期是否在指定日期之后
		while (dEnd.after(calBegin.getTime())) {
			// 根据日历的规则，给定的日历字段增加或减去指定的时间量
			calBegin.add(Calendar.DAY_OF_MONTH, 1);
			String dayStr = sdf.format(calBegin.getTime());
			daysStrList.add(dayStr);
		}

		//打印测试数据
		//System.out.println("#####################："+daysStrList);

		return daysStrList;
	}


}
